package com.zaoke.web.service.food.impl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;
import com.zaoke.web.bo.food.Food;
import com.zaoke.web.bo.food.FoodImage;
import com.zaoke.web.bo.food.FoodNutrition;
import com.zaoke.web.bo.food.FoodPromotion;
import com.zaoke.web.bo.food.FoodTag;
import com.zaoke.web.bo.food.Nutrition;
import com.zaoke.web.bo.query.food.FoodSave;
import com.zaoke.web.bo.query.food.PromotionSave;
import com.zaoke.web.dao.food.FoodDao;
import com.zaoke.web.dao.food.FoodImageDao;
import com.zaoke.web.dao.food.FoodNutritionDao;
import com.zaoke.web.dao.food.FoodPromotionDao;
import com.zaoke.web.dao.food.FoodTagsDao;
import com.zaoke.web.dao.food.NutritionDao;
import com.zaoke.web.service.food.FoodService;

public class FoodServiceImpl implements FoodService{
	
	private FoodDao foodDao;
	
	private FoodImageDao foodImageDao;
	
	private FoodNutritionDao foodNutritionDao;
	
	private FoodPromotionDao foodPromotionDao;
	
	private FoodTagsDao foodTagsDao;
	
	private NutritionDao nutritionDao;
	
	private String fileDir = "";
	
	private long expireTime;

	public Food getFoodById(long foodId,boolean readDB) {
		
		if(!readDB)
		{
			Set<Food> foods = getAllActiveFoods(false);
			
			if(foods != null && foods.size() > 0)
				for(Food food : foods)
					if(food.getId() == foodId)
						return food;
		}
		else
		{
			Food food = foodDao.getFoodById(foodId);
			List<FoodImage> image = foodImageDao.getImageByFoodId(foodId, true);
			Set<Long> idSet = new HashSet<Long>();
			idSet.add(foodId);
			List<FoodNutrition> nutritions = foodNutritionDao.getNutritionsByFoodIds(idSet);
			List<FoodTag> tags = foodTagsDao.getTagsByFoodIds(idSet);
			if(food!=null)
			{
				if(image != null)
					for(FoodImage im : image)
						if(im.getType() == FoodImage.TYPE_APP)
							food.setImage(im);
						else if(im.getType() == FoodImage.TYPE_PC)
							food.setImagepc(im);
				food.setNutritions(nutritions);
				food.setTags(tags);
			}
				
			return food;
		}
		return null;
	}
	
	public Set<Food> getAllActiveFoods(boolean needDetail){
		
		Set<Food> foods = foodDao.getFoodsByState(new Integer[]{Food.STATE_ACTIVE,Food.STATE_INACTIVE});
		
		if(needDetail)
		{
			if(foods!=null && foods.size()>0)
			{
				Set<Long> foodids = new HashSet<Long>();
				for(Food food : foods)
				{
					foodids.add(food.getId());
				}
				List<FoodImage> images = foodImageDao.getImagesByFoodIds(foodids,false);
				
				
				Map<Long,FoodImage> imageMap = new HashMap<Long, FoodImage>();
				Map<Long,FoodImage> imageMapPC = new HashMap<Long, FoodImage>();
				Map<Long,List<FoodNutrition>> nutritionMap = new HashMap<Long, List<FoodNutrition>>();
				Map<Long,List<FoodTag>> tagMap = new HashMap<Long, List<FoodTag>>();
				
				if(images!=null && images.size()>0)
				{
					for(FoodImage image : images)
					{
						if(image.getType() == FoodImage.TYPE_APP)
							imageMap.put(image.getFoodid(), image);
						if(image.getType() == FoodImage.TYPE_PC)
							imageMapPC.put(image.getFoodid(), image);
					}
				}
				images = null;
				List<FoodNutrition> nutritions = foodNutritionDao.getNutritionsByFoodIds(foodids);
				List<FoodTag> tags = foodTagsDao.getTagsByFoodIds(foodids);
				if(nutritions!=null && nutritions.size()>0)
				{
					for(FoodNutrition nu : nutritions)
					{
						if(nutritionMap.get(nu.getFoodid())==null)
						{
							List<FoodNutrition> nus = new ArrayList<FoodNutrition>();
							nutritionMap.put(nu.getFoodid(), nus);
						}
						nutritionMap.get(nu.getFoodid()).add(nu);
					}
				}
				
				if(tags!=null && tags.size()>0)
				{
					for(FoodTag tag : tags)
					{
						if(tagMap.get(tag.getFoodid())==null)
						{
							List<FoodTag> taglist = new ArrayList<FoodTag>();
							tagMap.put(tag.getFoodid(), taglist);
						}
						tagMap.get(tag.getFoodid()).add(tag);
					}
				}
				
				for(Food food : foods)
				{
					food.setImage(imageMap.get(food.getId()));
					food.setImagepc(imageMapPC.get(food.getId()));
					food.setTags(tagMap.get(food.getId()));
					food.setNutritions(nutritionMap.get(food.getId()));
				}
				
			}
				
		}
		
		return foods;
	}

	public FoodDao getFoodDao() {
		return foodDao;
	}

	public void setFoodDao(FoodDao foodDao) {
		this.foodDao = foodDao;
	}

	public long getExpireTime() {
		return expireTime;
	}

	public void setExpireTime(long expireTime) {
		this.expireTime = expireTime;
	}

	@Override
	public boolean newFood(FoodSave input) {
		boolean res = true;
		if(input==null)
			return false;
		long userid = input.getUserid();
		Food fin = new Food();
		fin.setName(input.getName());
		fin.setType(input.getType());
		fin.setSalePrice(input.getPrice());
		fin.setState(input.getState());
		fin.setUserid(userid);
		fin.setDesc(input.getDesc());
		
		FoodImage fimage = new FoodImage();
		List<FoodNutrition> nutritions = new ArrayList<FoodNutrition>();
		List<FoodTag> tags = new ArrayList<FoodTag>();
		
		Food food = foodDao.newFood(fin);
		if(food==null)
		{
			res = false;
			return res;
		}
		long foodid = food.getId();
		
		// app
		fimage.setFoodid(foodid);
		
		String image = input.getImage();
		String[] splits = image.split(";");
		String filetype = splits[0].split("/")[1];
		String filecontent = splits[1].split(",")[1];
		
		byte[] buffer;
		fimage.setType(FoodImage.TYPE_APP);
		try {
			buffer = Base64.decode(filecontent);
			String _name = food.getType()+"food_"+foodid+ "_" + fimage.getType() + "."+filetype;
			String filename = fileDir+_name;
			fimage.setUrl(_name);
			fimage.setContent(image);
			FileOutputStream fs;
			fs = new FileOutputStream(filename);
            fs.write(buffer); 
		} catch (Base64DecodingException e) {
			e.printStackTrace();
		}catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		fimage.setUserid(userid);
		res = res&foodImageDao.newFoodImage(fimage);

		// pc
		image = input.getImagepc();
		if(StringUtils.isNotBlank(image)){
			fimage = new FoodImage();
			fimage.setFoodid(foodid);
			splits = image.split(";");
			filetype = splits[0].split("/")[1];
			filecontent = splits[1].split(",")[1];
	
			fimage.setType(FoodImage.TYPE_PC);
			try {
				buffer = Base64.decode(filecontent);
				String _name = food.getType()+"food_"+foodid+ "_" + fimage.getType() + "."+filetype;
				String filename = fileDir+_name;
				fimage.setUrl(_name);
				fimage.setContent(image);
				FileOutputStream fs;
				fs = new FileOutputStream(filename);
	            fs.write(buffer); 
			} catch (Base64DecodingException e) {
				e.printStackTrace();
			}catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			fimage.setUserid(userid);
			res = res&foodImageDao.newFoodImage(fimage);
		}
		
		if(StringUtils.isNotBlank(input.getCalorie()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.calorie);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getCalorie());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getCarbo()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.carbo);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getCarbo());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getDf()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.df);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getDf());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getFat()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.fat);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getFat());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getMineral()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.mineral);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getMineral());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getProtein()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.protein);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getProtein());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getVitamin()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.vitamin);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getVitamin());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getValue()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.value);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getValue());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		
		if(nutritions != null && nutritions.size() > 0)
			res = res&foodNutritionDao.newNutritions(nutritions);
		
		if(StringUtils.isNotBlank(input.getFlag1()))
		{
			FoodTag tag = new FoodTag();
			tag.setFoodid(foodid);
			tag.setTag(input.getFlag1());
			tag.setUserid(userid);
			tags.add(tag);
		}
		if(StringUtils.isNotBlank(input.getFlag2()))
		{
			FoodTag tag = new FoodTag();
			tag.setFoodid(foodid);
			tag.setTag(input.getFlag2());
			tag.setUserid(userid);
			tags.add(tag);
		}
		if(StringUtils.isNotBlank(input.getFlag3()))
		{
			FoodTag tag = new FoodTag();
			tag.setFoodid(foodid);
			tag.setTag(input.getFlag3());
			tag.setUserid(userid);
			tags.add(tag);
		}
		if(StringUtils.isNotBlank(input.getFlag4()))
		{
			FoodTag tag = new FoodTag();
			tag.setFoodid(foodid);
			tag.setTag(input.getFlag4());
			tag.setUserid(userid);
			tags.add(tag);
		}
		if(StringUtils.isNotBlank(input.getFlag5()))
		{
			FoodTag tag = new FoodTag();
			tag.setFoodid(foodid);
			tag.setTag(input.getFlag5());
			tag.setUserid(userid);
			tags.add(tag);
		}
		
		if(tags != null && tags.size() > 0)
			res = res&foodTagsDao.newTags(tags);
		
		return res;
	}

	public void setFoodImageDao(FoodImageDao foodImageDao) {
		this.foodImageDao = foodImageDao;
	}

	public void setFoodNutritionDao(FoodNutritionDao foodNutritionDao) {
		this.foodNutritionDao = foodNutritionDao;
	}

	public void setFoodPromotionDao(FoodPromotionDao foodPromotionDao) {
		this.foodPromotionDao = foodPromotionDao;
	}

	public void setFoodTagsDao(FoodTagsDao foodTagsDao) {
		this.foodTagsDao = foodTagsDao;
	}

	public void setNutritionDao(NutritionDao nutritionDao) {
		this.nutritionDao = nutritionDao;
	}

	public void setFileDir(String fileDir) {
		this.fileDir = fileDir;
	}

	@Override
	public boolean updateFood(FoodSave input) {
		boolean res = true;
		if(input==null)
			return false;
		long userid = input.getUserid();
		long foodid = input.getFoodid();
		Food fin = new Food();
		fin.setName(input.getName());
		fin.setType(input.getType());
		fin.setSalePrice(input.getPrice());
		fin.setState(input.getState());
		fin.setUserid(userid);
		fin.setDesc(input.getDesc());
		fin.setId(foodid);
		fin.setSequence(input.getSequence());
		
		FoodImage fimage = new FoodImage();
		List<FoodNutrition> nutritions = new ArrayList<FoodNutrition>();
		List<FoodTag> tags = new ArrayList<FoodTag>();
		
		res = res&foodDao.updateFood(fin);
//		System.out.println("##############" + res);
		if(!res)
			return res;
		
		fimage.setFoodid(foodid);
		String image = input.getImage();
		String[] splits = image.split(";");
		String filetype = splits[0].split("/")[1];
		String filecontent = splits[1].split(",")[1];
		
		byte[] buffer;
		fimage.setType(FoodImage.TYPE_APP);
		try {
			buffer = Base64.decode(filecontent);
			String _name = fin.getType()+"food_"+foodid+ "_" + fimage.getType() + "."+filetype;
			String filename = fileDir+_name;
			File file = new File(filename);
			if(file.exists())
			{
				file.delete();
			}
			fimage.setUrl(_name);
			fimage.setContent(image);
			FileOutputStream fs;
			fs = new FileOutputStream(filename);
            fs.write(buffer); 
		} catch (Base64DecodingException e) {
			e.printStackTrace();
		}catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		fimage.setUserid(userid);
		
		res = res&foodImageDao.updateFoodImage(fimage);
//		System.out.println("##############" + res);
		
		if(!res)
			return res;
		
		// pc
		image = input.getImagepc();
		if(StringUtils.isNotBlank(image)){
			fimage = new FoodImage();
			fimage.setFoodid(foodid);
			splits = image.split(";");
			filetype = splits[0].split("/")[1];
			filecontent = splits[1].split(",")[1];
	
			fimage.setType(FoodImage.TYPE_PC);
			try {
				buffer = Base64.decode(filecontent);
				String _name = fin.getType()+"food_"+foodid+ "_" + fimage.getType() + "."+filetype;
				String filename = fileDir+_name;
				File file = new File(filename);
				if(file.exists())
				{
					file.delete();
				}
				fimage.setUrl(_name);
				fimage.setContent(image);
				FileOutputStream fs;
				fs = new FileOutputStream(filename);
	            fs.write(buffer); 
			} catch (Base64DecodingException e) {
				e.printStackTrace();
			}catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			fimage.setUserid(userid);
			res = res&foodImageDao.updateFoodImage(fimage);
//			System.out.println("##############" + res);
			if(!res)
				return res;
		}
		
		if(StringUtils.isNotBlank(input.getCalorie()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.calorie);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getCalorie());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getCarbo()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.carbo);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getCarbo());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getDf()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.df);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getDf());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getFat()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.fat);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getFat());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getMineral()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.mineral);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getMineral());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getProtein()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.protein);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getProtein());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getVitamin()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.vitamin);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getVitamin());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		if(StringUtils.isNotBlank(input.getValue()))
		{
			FoodNutrition nutrition = new FoodNutrition();
			nutrition.setFoodid(foodid);
			Nutrition nu = nutritionDao.findNutritionByName(Nutrition.value);
			nutrition.setNutrition(nu);
			nutrition.setValue(input.getValue());
			nutrition.setUserid(userid);
			nutritions.add(nutrition);
		}
		
		if(nutritions != null && nutritions.size() > 0)
			res = res&foodNutritionDao.updateNutritions(nutritions,foodid);

//		System.out.println("##############" + res);
		if(!res)
			return res;
		
		if(StringUtils.isNotBlank(input.getFlag1()))
		{
			FoodTag tag = new FoodTag();
			tag.setFoodid(foodid);
			tag.setTag(input.getFlag1());
			tag.setUserid(userid);
			tags.add(tag);
		}
		if(StringUtils.isNotBlank(input.getFlag2()))
		{
			FoodTag tag = new FoodTag();
			tag.setFoodid(foodid);
			tag.setTag(input.getFlag2());
			tag.setUserid(userid);
			tags.add(tag);
		}
		if(StringUtils.isNotBlank(input.getFlag3()))
		{
			FoodTag tag = new FoodTag();
			tag.setFoodid(foodid);
			tag.setTag(input.getFlag3());
			tag.setUserid(userid);
			tags.add(tag);
		}
		if(StringUtils.isNotBlank(input.getFlag4()))
		{
			FoodTag tag = new FoodTag();
			tag.setFoodid(foodid);
			tag.setTag(input.getFlag4());
			tag.setUserid(userid);
			tags.add(tag);
		}
		if(StringUtils.isNotBlank(input.getFlag5()))
		{
			FoodTag tag = new FoodTag();
			tag.setFoodid(foodid);
			tag.setTag(input.getFlag5());
			tag.setUserid(userid);
			tags.add(tag);
		}
		
		if(tags != null && tags.size() > 0)
			res = res&foodTagsDao.updateTags(tags,foodid);

//		System.out.println("##############" + res);
		return res;
	}

	@Override
	public boolean deleteFood(Long foodid) {
		
		boolean res = true;
		res = res&foodDao.deleteFood(foodid);
		res = res&foodImageDao.deleteImage(foodid);
		res = res&foodNutritionDao.deleteNutritions(foodid);
		res = res&foodTagsDao.deleteTags(foodid);
		res = res&foodPromotionDao.deletePromotionByFoodId(foodid);
		return res;
	}

	@Override
	public boolean newPromotion(PromotionSave input) {
		
		FoodPromotion promotion = new FoodPromotion();
		promotion.setFoodid(input.getFoodid());
		promotion.setComboMargin(input.getCombomargin());
		promotion.setSingleMargin(input.getSinglemargin());
		promotion.setPromotionDate(input.getFooddate());
		Long userid = input.getUserid();
		
		return foodPromotionDao.newFoodPromotion(promotion, userid);
		
	}
	
	@Override
	public boolean updatePromotion(PromotionSave input) {
		
		FoodPromotion promotion = new FoodPromotion();
		promotion.setId(input.getId());
		promotion.setFoodid(input.getFoodid());
		promotion.setComboMargin(input.getCombomargin());
		promotion.setSingleMargin(input.getSinglemargin());
		promotion.setPromotionDate(input.getFooddate());
		Long userid = input.getUserid();
		
		return foodPromotionDao.updateFoodPromotion(promotion, userid);
		
	}

	@Override
	public List<FoodPromotion> getAllActivePromotions() {
		return foodPromotionDao.getAllActivePromotions(new Integer[]{FoodPromotion.STATE_ACTIVE});
	}

	@Override
	public FoodPromotion getPromotionById(Long id) {
		return foodPromotionDao.getPromotionById(id);
	}

	@Override
	public boolean deletePromotion(Long id) {
		return foodPromotionDao.deletePromotionById(id);
	}
	
}
